package com.jingfang.cloud.widget.main;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.fazecast.jSerialComm.SerialPort;
import com.formdev.flatlaf.FlatClientProperties;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import com.jingfang.cloud.MzContext;
import com.jingfang.cloud.MzPrefs;
import com.jingfang.cloud.constant.enums.Command;
import com.jingfang.cloud.constant.ui.Resources;
import com.jingfang.cloud.core.SerialPortService;
import com.jingfang.cloud.core.event.StartCommandEvent;
import com.jingfang.cloud.core.event.StopCommandEvent;
import com.jingfang.cloud.core.model.ResultModel;
import com.jingfang.cloud.widget.show.ShowDialog;
import lombok.Data;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.text.StyleContext;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;

@Data
public class MainComponent implements ActionListener {
    private final MainWidget owner;
    private final MzContext context;
    private final MzPrefs prefs;
    private JPanel contentPanel;
    private JButton startBtn;
    private JRadioButton lowRadio;
    private JRadioButton middleRadio;
    private JRadioButton heightRadio;
    private JLabel taskStateLabel;
    private JLabel taskTimeLabel;
    private JLabel connectStateLabel;
    private Boolean started = false;
    private int seconds = 0;
    private String taskName = null;
    private String taskId = null;

    public MainComponent(MainWidget owner) {
        this.owner = owner;
        this.context = (MzContext) owner.getContext();
        this.prefs = owner.getPrefs();
        this.initUI();
        this.initComponents();
    }

    Timer runningTxtTimer = new Timer(1300, event -> {
        seconds++;
        updateStopwatchDisplay();
    });

    public void initUI() {
        startBtn.setIcon(Resources.EXECUTE_ICON);
        startBtn.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_BORDERLESS);
        startBtn.putClientProperty(FlatClientProperties.SQUARE_SIZE, 100);
        startBtn.setFocusable(false);
        startBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        startBtn.setBackground(new Color(168, 202, 176, 137));
        startBtn.setMargin(new Insets(0, 30, 0, 30));
        connectStateLabel.setIcon(Resources.CONNECT_SUCCESS_ICON);
        taskTimeLabel.setText("-:-:-");
        this.taskStyleChange(false);
    }

    public void initComponents() {
        SerialPortService serialPortService = owner.getSerialPortService();
        SerialPort serialPort = serialPortService.getSerialPort();
        String descriptivePortName = serialPort.getDescriptivePortName();
        connectStateLabel.setText("<html>" + descriptivePortName + " [ <font color='#0466FAFF'>" + serialPort.getSystemPortName() + "</font> ] 连接成功. </html>");
        this.startBtn.addActionListener(this);
        this.lowRadio.setSelected(true);
        this.lowRadio.addActionListener(e -> {
            lowRadio.setSelected(true);
            middleRadio.setSelected(false);
            heightRadio.setSelected(false);
        });
        this.middleRadio.addActionListener(e -> {
            lowRadio.setSelected(false);
            middleRadio.setSelected(true);
            heightRadio.setSelected(false);
        });
        this.heightRadio.addActionListener(e -> {
            lowRadio.setSelected(false);
            middleRadio.setSelected(false);
            heightRadio.setSelected(true);
        });
    }

    private void updateStopwatchDisplay() {
        int hours = seconds / 3600;
        int minutes = (seconds % 3600) / 60;
        int secs = seconds % 60;
        if (secs < 8 && taskStateLabel.getText().equals("-")) {
            taskStateLabel.setText("准备中");
        } else if (secs == 8 && taskStateLabel.getText().equals("准备中")) {
            taskStateLabel.setText("采集中");
            seconds = 0;
        } else {
            taskTimeLabel.setText(String.format("%02d:%02d:%02d", hours, minutes, secs));
        }

    }

    private void taskStyleChange(boolean started) {
        if (started) {
            seconds = 0;
            runningTxtTimer.start();
            taskStateLabel.setText("-");
            taskStateLabel.setForeground(Color.decode("#59A869"));
            startBtn.setToolTipText("点击终止任务！");
            startBtn.setBackground(new Color(202, 168, 172, 137));
            startBtn.setIcon(Resources.PAUSE_ICON);
        } else {
            taskStateLabel.setForeground(new Color(-1028016));
            startBtn.setToolTipText("点击启动任务！");
            startBtn.setBackground(new Color(168, 202, 176, 137));
            startBtn.setIcon(Resources.EXECUTE_ICON);
            runningTxtTimer.stop();
        }
        startBtn.setEnabled(true);
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        contentPanel = new JPanel();
        contentPanel.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1));
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new GridLayoutManager(7, 5, new Insets(50, 0, 0, 0), -1, -1));
        contentPanel.add(panel1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final Spacer spacer1 = new Spacer();
        panel1.add(spacer1, new GridConstraints(0, 4, 7, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
        final Spacer spacer2 = new Spacer();
        panel1.add(spacer2, new GridConstraints(0, 0, 7, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
        lowRadio = new JRadioButton();
        Font lowRadioFont = this.$$$getFont$$$(null, Font.BOLD, 16, lowRadio.getFont());
        if (lowRadioFont != null) lowRadio.setFont(lowRadioFont);
        lowRadio.setText("浮力");
        panel1.add(lowRadio, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        middleRadio = new JRadioButton();
        Font middleRadioFont = this.$$$getFont$$$(null, Font.BOLD, 16, middleRadio.getFont());
        if (middleRadioFont != null) middleRadio.setFont(middleRadioFont);
        middleRadio.setText("中力");
        panel1.add(middleRadio, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        heightRadio = new JRadioButton();
        Font heightRadioFont = this.$$$getFont$$$(null, Font.BOLD, 16, heightRadio.getFont());
        if (heightRadioFont != null) heightRadio.setFont(heightRadioFont);
        heightRadio.setText("沉力");
        panel1.add(heightRadio, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JLabel label1 = new JLabel();
        Font label1Font = this.$$$getFont$$$(null, -1, 15, label1.getFont());
        if (label1Font != null) label1.setFont(label1Font);
        label1.setText("状态: ");
        panel1.add(label1, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        taskStateLabel = new JLabel();
        Font taskStateLabelFont = this.$$$getFont$$$(null, -1, 14, taskStateLabel.getFont());
        if (taskStateLabelFont != null) taskStateLabel.setFont(taskStateLabelFont);
        taskStateLabel.setText("-");
        panel1.add(taskStateLabel, new GridConstraints(2, 2, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        taskTimeLabel = new JLabel();
        Font taskTimeLabelFont = this.$$$getFont$$$(null, -1, 14, taskTimeLabel.getFont());
        if (taskTimeLabelFont != null) taskTimeLabel.setFont(taskTimeLabelFont);
        taskTimeLabel.setText("-:-:-");
        panel1.add(taskTimeLabel, new GridConstraints(3, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JLabel label2 = new JLabel();
        Font label2Font = this.$$$getFont$$$(null, Font.PLAIN, 15, label2.getFont());
        if (label2Font != null) label2.setFont(label2Font);
        label2.setText("计时: ");
        panel1.add(label2, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JSeparator separator1 = new JSeparator();
        panel1.add(separator1, new GridConstraints(1, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
        final JSeparator separator2 = new JSeparator();
        panel1.add(separator2, new GridConstraints(4, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, new Dimension(200, -1), null, null, 0, false));
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new GridLayoutManager(1, 1, new Insets(10, 0, 0, 0), -1, -1));
        panel1.add(panel2, new GridConstraints(5, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        startBtn = new JButton();
        startBtn.setMargin(new Insets(50, 0, 0, 0));
        startBtn.setText("");
        panel2.add(startBtn, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, new Dimension(160, 160), new Dimension(150, 150), null, 0, false));
        final Spacer spacer3 = new Spacer();
        contentPanel.add(spacer3, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
        final JLabel label3 = new JLabel();
        label3.setText("Label");
        label3.setVisible(false);
        contentPanel.add(label3, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JPanel panel3 = new JPanel();
        panel3.setLayout(new GridLayoutManager(1, 2, new Insets(10, 10, 0, 0), -1, -1));
        contentPanel.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        connectStateLabel = new JLabel();
        connectStateLabel.setText("Label");
        panel3.add(connectStateLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final Spacer spacer4 = new Spacer();
        panel3.add(spacer4, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
    }

    /**
     * @noinspection ALL
     */
    private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) {
        if (currentFont == null) return null;
        String resultName;
        if (fontName == null) {
            resultName = currentFont.getName();
        } else {
            Font testFont = new Font(fontName, Font.PLAIN, 10);
            if (testFont.canDisplay('a') && testFont.canDisplay('1')) {
                resultName = fontName;
            } else {
                resultName = currentFont.getName();
            }
        }
        Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize());
        boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac");
        Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize());
        return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return contentPanel;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (started) {

            final String dir = buildFileDir();
            this.runningTxtTimer.stop();
            this.started = false;
            this.taskStateLabel.setText("采集结束");
            this.startBtn.setEnabled(false);
            this.taskStyleChange(false);
            this.context.getEventBus().publish(new StopCommandEvent(taskId));
            final ResultModel resultModel = new ResultModel();
            resultModel.setDuration(seconds);
            resultModel.setOperationTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            resultModel.setOperationType(taskName);
            final ShowDialog showDialog = new ShowDialog(owner, FileUtil.newFile(dir + File.separator + taskId + "_" + taskName + ".dat"), resultModel);
            showDialog.setVisible(true);
            this.taskId = null;
            this.startBtn.setEnabled(true);

        } else {
            this.taskId = DateUtil.format(new Date(), "yyyyMMddHHmmss");
            this.taskName = lowRadio.getText();
            this.started = true;
            final String dir = buildFileDir();
            Command command = Command.START_LOW;
            if (heightRadio.isSelected()) {
                taskName = heightRadio.getText();
                command = Command.START_HEIGHT;
            }
            if (middleRadio.isSelected()) {
                taskName = middleRadio.getText();
                command = Command.START_MIDDLE;
            }
            try {
                FileUtil.mkdir(dir);
                File newFile = FileUtil.newFile(dir + File.separator + taskId + "_" + taskName + ".dat");
                boolean file = newFile.createNewFile();
                if (file) {
                    this.context.getEventBus().publish(new StartCommandEvent(newFile.getAbsolutePath(), command));
                } else {
                    this.owner.displayMessage("文件创建失败", newFile.getAbsolutePath());
                    return;
                }
            } catch (IOException ex) {
                this.owner.displayException("文件创建失败", ex);
                return;
            }
            this.taskStyleChange(started);
        }

    }

    private @NotNull String buildFileDir() {
        return System.getProperty("user.dir") + File.separator + "data" + File.separator + DateUtil.format(new Date(), "yyyyMMdd") + File.separator + taskId;
    }
}
